home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / pgpsrc23 / rsaglue.c < prev    next >
C/C++ Source or Header  |  1993-06-10  |  16KB  |  532 lines

  1. /* rsaglue.c - These functions wrap and unwrap message digests (MDs) and
  2.  * data encryption keys (DEKs) in padding and RSA-encrypt them into
  3.  * multi-precision integers.  This layer was introduced to allow the
  4.  * transparent use of RSAREF for the encryption (in regions where it is
  5.  * legally available - the U.S. and treaty partners), or Philip Zimmermann's
  6.  * mpi library (where permitted by patent law - outside the U.S.).
  7.  *
  8.  * These functions also hide the details of using either PKCS or PGP 2.0
  9.  * style padding and encodings within the integers.  See pgformat.doc
  10.  * for a detailed description of the formats.
  11.  */
  12.  
  13. #include <string.h>     /* for mem*() */
  14. #include "mpilib.h"
  15. #include "mpiio.h"
  16. #include "pgp.h"
  17. #include "rsaglue.h"
  18.  
  19. #ifdef RSAREF        /* defined (or not) in rsaglue.h */
  20. #include "rsaref/test/global.h"
  21. #include "rsaref/source/rsa.h"
  22. #include "rsaref/source/rsaref.h"
  23.  
  24. int RSAPublicBlock(byte *dest, unsigned *destbytesptr,
  25.                    byte *src, unsigned srcbytes,
  26.                    R_RSA_PUBLIC_KEY *PubKey);
  27. int RSAPrivateBlock(byte *dest, unsigned *destbytesptr,
  28.                     byte *src, unsigned srcbytes,
  29.                     R_RSA_PRIVATE_KEY *PrivKey);
  30.  
  31. /* Functions to convert to and from RSAREF's bignum formats */
  32.  
  33. void
  34. rsaref2reg (unitptr to, byte *from, int frombytes)
  35. /* Convert an RSAREF-style MSB-first array of bytes to an mpi-style
  36.  * native-byte-order integer.  (global_precision units long.)
  37.  */
  38. {
  39.     int tobytes;
  40.  
  41.     tobytes = units2bytes (global_precision);
  42.     if (tobytes > frombytes) {
  43.         memset(to, 0, tobytes - frombytes);
  44.         memcpy((byte *)to + tobytes - frombytes, from, frombytes);
  45.     } else {
  46.         memcpy((byte *)to, from + frombytes - tobytes, tobytes);
  47.     }
  48. #ifndef HIGHFIRST
  49.     hiloswap((byte *)to, tobytes);
  50. #endif
  51. } /* rsaref2reg */
  52.  
  53. void
  54. reg2rsaref (byte *to, int tobytes, unitptr from)
  55. /* Convert the other way, mpi format to an array of bytes. */
  56. {
  57.     int frombytes;
  58.  
  59.     frombytes = units2bytes(global_precision);
  60.  
  61. #ifdef HIGHFIRST
  62.     if (tobytes > frombytes) {
  63.         memset(to, 0, tobytes-frombytes);
  64.         memcpy(to + tobytes - frombytes, (byte *)from, frombytes);
  65.     } else {
  66.         memcpy(to, (byte *)from + frombytes - tobytes, tobytes);
  67.     }
  68. #else
  69.     if (tobytes > frombytes) {
  70.         memcpy(to, (byte *)from, frombytes);
  71.         memset(to + frombytes, 0, tobytes-frombytes);
  72.     } else {
  73.         memcpy(to, (byte *)from, tobytes);
  74.     }
  75.     hiloswap(to, tobytes);
  76. #endif
  77. } /* reg2rsaref */
  78.  
  79. int
  80. make_RSA_PUBLIC_KEY(R_RSA_PUBLIC_KEY *rpk, unitptr e, unitptr n)
  81. /* Given mpi's e and n, fill in an R_RSA_PUBLIC_KEY structure.
  82.  * Returns -1 on error, 0 on success
  83.  */
  84. {
  85.     rpk->bits = countbits(n);
  86.     if (rpk->bits > MAX_RSA_MODULUS_BITS)
  87.         return -1;
  88.  
  89.     reg2rsaref(rpk->modulus, MAX_RSA_MODULUS_LEN, n);
  90.     reg2rsaref(rpk->exponent, MAX_RSA_MODULUS_LEN, e);
  91.     return 0;
  92. } /* make_RSA_PUBLIC_KEY */
  93.   
  94. /* Returns -1 on error, 0 on success */
  95. int
  96. make_RSA_PRIVATE_KEY(R_RSA_PRIVATE_KEY *rpk, unitptr e, unitptr d, unitptr p,
  97.                      unitptr q, unitptr dp, unitptr dq, unitptr u, unitptr n)
  98. /* Given a number of necessary mpi's, fill in an R_RSA_PRIVATE_KEY structure.
  99.  * Returns -1 on error, 0 on success
  100.  */
  101. {
  102.     rpk->bits = countbits(n);
  103.     if (rpk->bits > MAX_RSA_MODULUS_BITS ||
  104.         countbits(p) > MAX_RSA_PRIME_BITS ||
  105.         countbits(q) > MAX_RSA_PRIME_BITS)
  106.         return -1;
  107.  
  108.     reg2rsaref(rpk->modulus, MAX_RSA_MODULUS_LEN, n);
  109.     reg2rsaref(rpk->publicExponent, MAX_RSA_MODULUS_LEN, e);
  110.     reg2rsaref(rpk->exponent, MAX_RSA_MODULUS_LEN, d);
  111.     /* The larger prime (p) first */
  112.     reg2rsaref(rpk->prime[0], MAX_RSA_PRIME_LEN, q);
  113.     reg2rsaref(rpk->prime[1], MAX_RSA_PRIME_LEN, p);
  114.     /* d mod (p-1) and d mod (q-1) */
  115.     reg2rsaref(rpk->primeExponent[0], MAX_RSA_PRIME_LEN, dq);
  116.     reg2rsaref(rpk->primeExponent[1], MAX_RSA_PRIME_LEN, dp);
  117.     /* 1/q mod p */
  118.     reg2rsaref(rpk->coefficient, MAX_RSA_PRIME_LEN, u);
  119.     return 0;
  120. } /* make_RSA_PRIVATE_KEY */
  121.  
  122. #endif /* RSAREF */
  123.  
  124. /* These functions hide all the internal details of RSA-encrypted
  125.  * keys and digests.  They owe a lot of their heritage to
  126.  * the preblock() and postunblock() routines in mpiio.c.
  127.  */
  128.  
  129. /* Abstract Syntax Notation One (ASN.1) Distinguished Encoding Rules (DER)
  130.    encoding for RSA/MD5, used in PKCS-format signatures. */
  131. static byte asn_array[] = {    /* PKCS 01 block type 01 data */
  132.     0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
  133.     0x02,0x05,0x05,0x00,0x04,0x10 };
  134. /* This many bytes from the end, there's a zero byte */
  135. #define ASN_ZERO_END 3
  136.  
  137. int
  138. rsa_public_encrypt(unitptr outbuf, byteptr inbuf, short bytes,
  139.      unitptr E, unitptr N)
  140. /* Encrypt a DEK with a public key.  Returns 0 on success.
  141.  * <0 means there was an error
  142.  */
  143. {
  144.     unit temp[MAX_UNIT_PRECISION];
  145. #ifdef RSAREF
  146.     R_RSA_PUBLIC_KEY PubKey;
  147.     R_RANDOM_STRUCT Random;
  148. #endif /* RSAREF */
  149.     unsigned int blocksize;
  150.     byte *p;
  151.     int i;    /* Temporary, and holds error codes */
  152.  
  153.     blocksize = countbytes(N) - 1;    /* Bytes available for user data */
  154.  
  155.     p = (byte *)temp;
  156.  
  157. #ifdef RSAREF
  158.     /* Fill in the R_RSA_PUBLIC_KEY structure as needed later. */
  159.     i = make_RSA_PUBLIC_KEY(&PubKey, E, N);
  160.     if (i < 0)
  161.         return -1;
  162. #else /* !RSAREF */
  163.     /* If !RSAREF, we are building the mpi in place, except for a
  164.      * possible byte-order swap to little-endian at the end.  Thus,
  165.      * we need to fill the buffer with leading 0's in the unused
  166.      * most significant byte positions.
  167.      */
  168.     for (i = units2bytes(global_precision) - blocksize; i > 0; --i)
  169.         *p++ = 0;
  170. #endif /* !RSAREF */
  171.  
  172.     /* Both the PKCS and PGP 2.0 key formats add a type byte, and a
  173.      * a framing byte of 0 to the user data.  The remaining space
  174.      * is filled with random padding.  (PKCS requires that there be
  175.      * at least 1 byte of padding.)
  176.      */
  177.     i = blocksize - 2 - bytes;
  178.  
  179.     if (pkcs_compat) {
  180.         if (i < 1)        /* Less than minimum padding? */
  181.             return -1;
  182. #ifndef RSAREF    /* Build the packet ourselves */
  183.         *p++ = CK_ENCRYPTED_BYTE;    /* Type byte */
  184.         while (i)            /* Non-zero random padding */
  185.             if ((*p = idearand()))
  186.                 ++p, --i;
  187.         *p++ = 0;            /* Framing byte */
  188.         memcpy(p, inbuf, bytes);    /* User data */
  189. #else /* RSAREF */
  190.         /* The RSAREF routines have their own random number generator
  191.          * to generate random padding.  The following code seeds it
  192.          * from PGP's random number generator.
  193.          */
  194.         R_RandomInit(&Random);
  195.         for (;;) {
  196.             R_GetRandomBytesNeeded(&i, &Random);
  197.             if (i <= 0)
  198.                 break;
  199.             blocksize = i > sizeof(temp) ? sizeof(temp) : i;
  200.             for (i = 0; i < blocksize; i++)
  201.                 ((byte *)temp)[i] = idearand();
  202.             R_RandomUpdate(&Random, (byte *)temp, blocksize);
  203.         }
  204.         /* Pad and encrypt */
  205.         i = RSAPublicEncrypt((byte *)temp, &blocksize,
  206.                              inbuf, bytes, &PubKey, &Random);
  207.         R_RandomFinal(&Random);    /* Clean up RSAREF's RNG */
  208.         burn(Random);        /* Just to be sure */
  209. #endif /* RSAREF */
  210.     } else {    /* !pkcs_compat */
  211.         if (i < 0)
  212.             return -1;
  213.         memcpy(p, inbuf, bytes);    /* User data */
  214.         p += bytes;
  215.         *p++ = 0;            /* Framing byte */
  216.         while (i)            /* Non-zero random padding */
  217.             if ((*p = idearand()))
  218.                 ++p, --i;
  219.         *p = CK_ENCRYPTED_BYTE;        /* Type byte */
  220. #ifdef RSAREF
  221.     /* Do the encryption */
  222.     i = RSAPublicBlock((byte *)temp, &blocksize,
  223.                        (byte *)temp, blocksize, &PubKey);
  224. #endif
  225.  
  226.     } /* !pkcs_compat */
  227.  
  228. #ifndef RSAREF
  229.     mp_convert_order((byte *)temp);        /* Convert buffer to MPI */
  230.     i = mp_modexp(outbuf, temp, E, N);    /* Do the encryption */
  231. #else /* RSAREF */
  232.     rsaref2reg(outbuf, (byte *)temp, blocksize);
  233. #endif /* RSAREF */
  234.  
  235. Cleanup:
  236.     mp_burn(temp);
  237. #ifdef RSAREF
  238.     burn(PubKey);
  239. #endif
  240.     return i < 0 ? i : 0;
  241. } /* rsa_public_encrypt */
  242.  
  243. int
  244. rsa_private_encrypt(unitptr outbuf, byteptr inbuf, short bytes,
  245.      unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N)
  246. /* Encrypt a message digest with a private key.
  247.  * Returns <0 on error.
  248.  */
  249. {
  250.     unit temp[MAX_UNIT_PRECISION];
  251.     unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION];
  252. #ifdef RSAREF
  253.     R_RSA_PRIVATE_KEY PrivKey;
  254. #else
  255.     int byte_precision;
  256. #endif
  257.     unsigned int blocksize;
  258.     byte *p;
  259.     int i;
  260.  
  261.     /* PGP doesn't store these coefficents, so we need to compute them. */
  262.     mp_move(temp,P);
  263.     mp_dec(temp);
  264.     mp_mod(DP,D,temp);
  265.     mp_move(temp,Q);
  266.     mp_dec(temp);
  267.     mp_mod(DQ,D,temp);
  268.  
  269.     blocksize = countbytes(N) - 1;    /* Space available for data */
  270.  
  271.     p = (byte *)temp;
  272.  
  273. #ifdef RSAREF
  274.     i = make_RSA_PRIVATE_KEY(&PrivKey, E, D, P, Q, DP, DQ, U, N);
  275.     if (i < 0)
  276.         goto Cleanup;
  277. #else
  278.     /* If !RSAREF, we are building the mpi in place, except for a
  279.      * possible byte-order swap to little-endian at the end.  Thus,
  280.      * we need to fill the buffer with leading 0's in the unused
  281.      * most significant byte positions.
  282.      */
  283.     for (i = units2bytes(global_precision) - blocksize; i > 0; --i)
  284.         *p++ = 0;
  285. #endif
  286.     i = blocksize - 2 - bytes;        /* Padding needed */
  287.  
  288.     if (pkcs_compat) {
  289. #ifndef RSAREF    /* Pad the packet ourselves */
  290.         i -= sizeof(asn_array);        /* Space for type encoding */
  291.         if (i < 0) {
  292.             i = -1;            /* Error code */
  293.             goto Cleanup;
  294.         }
  295.         *p++ = MD_ENCRYPTED_BYTE;    /* Type byte */
  296.         memset(p, ~0, i);        /* All 1's padding */
  297.         p += i;
  298.         *p++ = 0;            /* Zero framing byte */
  299. #endif /* !RSAREF */
  300.         memcpy(p, asn_array, sizeof(asn_array)); /* ASN data */
  301.         p += sizeof(asn_array);
  302.         memcpy(p, inbuf, bytes);    /* User data */
  303. #ifdef RSAREF
  304.         /* Pad and encrypt */
  305.         RSAPrivateEncrypt((byte *)temp, &blocksize,
  306.                           (byte *)temp, bytes+sizeof(asn_array),
  307.                           &PrivKey);
  308. #endif
  309.     } else {    /* Not pkcs_compat */
  310.         --i;                /* Space for type byte */
  311.         if (i < 0) {
  312.             i = -1;            /* Error code */
  313.             goto Cleanup;
  314.         }
  315.         *p++ = MD5_ALGORITHM_BYTE;    /* Algorithm type byte */
  316.         memcpy(p, inbuf, bytes);    /* User data */
  317.         p += bytes;
  318.         *p++ = 0;            /* Framing byte of 0 */
  319.         memset(p, ~0, i);        /* All 1's padding */
  320.         p += i;
  321.         *p = MD_ENCRYPTED_BYTE;        /* Type byte */
  322.  
  323. #ifdef RSAREF
  324.     /* Do the encryption */
  325.     i = RSAPrivateBlock((byte *)temp, &blocksize,
  326.                 (byte *)temp, blocksize, &PrivKey);
  327. #endif /* RSAREF */
  328.  
  329.     } /* !pkcs_compat */
  330.  
  331. #ifndef RSAREF
  332.     mp_convert_order((byte *)temp);
  333.     i = mp_modexp_crt(outbuf, temp, P, Q, DP, DQ, U);    /* Encrypt */
  334. #else /* RSAREF */
  335.     rsaref2reg(outbuf, (byte *)temp, blocksize);
  336. #endif /* RSAREF */
  337.  
  338. Cleanup:
  339.     mp_burn(temp);
  340. #ifdef RSAREF
  341.     memset(&PrivKey, 0, sizeof(PrivKey));
  342. #endif
  343.     return i < 0 ? i : 0;
  344. } /* rsa_private_encrypt */
  345.  
  346. /* Remove a signature packet from an MPI */
  347. /* Thus, we expect constant padding and the MIC ASN sequence */
  348. int
  349. rsa_public_decrypt(byteptr outbuf, unitptr inbuf,
  350.     unitptr E, unitptr N)
  351. /* Decrypt a message digest using a public key.  Returns the number of bytes
  352.  * extracted, or <0 on error.
  353.  * -1: Corrupted packet.
  354.  * -2: Unrecognized message digest algorithm.
  355.  */
  356. {
  357. #ifdef RSAREF
  358.     R_RSA_PUBLIC_KEY PubKey;
  359. #endif
  360.     unit temp[MAX_UNIT_PRECISION];
  361.     unsigned int blocksize;
  362.     int i;
  363.     byte *front, *back;
  364.  
  365. #ifdef RSAREF
  366.     make_RSA_PUBLIC_KEY(&PubKey, E, N);
  367.     blocksize = countbytes(inbuf);
  368.     reg2rsaref((byte *)temp, blocksize, inbuf);
  369.     RSAPublicBlock((byte *)temp, &blocksize,
  370.                        (byte *)temp, blocksize, &PubKey);
  371.  
  372.     front = (byte *)temp;            /* The start of the block */
  373.     back = front + blocksize;        /* The end */
  374.     i = blocksize - countbytes(N) + 1;    /* Expected leading 0's */
  375. #else
  376.     i = mp_modexp(temp, inbuf, E, N);
  377.     if (i < 0) {
  378.         mp_burn(temp);
  379.         return i;
  380.     }
  381.     mp_convert_order((byte *)temp);
  382.     blocksize = countbytes(N) - 1;
  383.     front = (byte *)temp;            /* Points to start of block */
  384.     i = units2bytes(global_precision);
  385.     back = front + i;            /* Points to end of block */
  386.     i -= countbytes(N) - 1;            /* Expected leading 0's */
  387. #endif
  388.  
  389.     /* This could be stricter, but the length returned by the RSAREF code
  390.        is not documented too well. */
  391.     if (i < 0)
  392.         goto ErrorReturn;
  393.     while (i--)        /* Any excess should be 0 */
  394.         if (*front++)
  395.             goto ErrorReturn;
  396.     /* front now points to the data */
  397.  
  398.     /* How to distinguish old PGP from PKCS formats.
  399.      * The old PGP format ends in a trailing type byte, with
  400.      * all 1's padding before that.  The PKCS format ends in
  401.      * 16 bytes of message digest, preceded by an ASN string
  402.      * which is not all 1's.
  403.      */
  404.     if (back[-1] == MD_ENCRYPTED_BYTE &&
  405.         back[-17] == 0xff && back[-18] == 0xff) {
  406.         /* Old PGP format: Padding is at the end */
  407.         if (*--back != MD_ENCRYPTED_BYTE)
  408.             goto ErrorReturn;
  409.         if (*front++ != MD5_ALGORITHM_BYTE) {
  410.             mp_burn(temp);
  411.             return -2;
  412.         }
  413.         while (*--back == 0xff)    /* Skip constant padding */
  414.             ;
  415.         if (*back)        /* It should end with a zero */
  416.             goto ErrorReturn;
  417.     } else {
  418.         /* PKCS format: padding at the beginning */
  419.         if (*front++ != MD_ENCRYPTED_BYTE)
  420.             goto ErrorReturn;
  421.         while (*front++ == 0xff) /* Skip constant padding */
  422.             ;
  423.         if (front[-1])    /* First non-FF byte should be 0 */
  424.             goto ErrorReturn;
  425.         /* Then comes the ASN header */
  426.         if (memcmp(front, asn_array, sizeof(asn_array))) {
  427.             mp_burn(temp);
  428.             return -2;
  429.         }
  430.         front += sizeof(asn_array);
  431. /* This is temporary - to be removed on release */
  432.         if (back-front == 17 && *front == MD5_ALGORITHM_BYTE) {
  433.             front++;
  434.             fprintf(stderr, "PGP 2.2b signature bug!\n");
  435.         }
  436.     }
  437. /* We're done - copy user data to outbuf */
  438.     if (back < front)
  439.         goto ErrorReturn;
  440.     memcpy(outbuf, front, back-front);
  441.     mp_burn(temp);
  442.     return back-front;
  443. ErrorReturn:
  444.     mp_burn(temp);
  445.     return -1;
  446. } /* rsa_public_decrypt */
  447.  
  448. /* We expect to find random padding and an encryption key */
  449. int
  450. rsa_private_decrypt(byteptr outbuf, unitptr inbuf,
  451.      unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N)
  452. /* Decrypt an encryption key using a private key.  Returns the number of bytes
  453.  * extracted, or <0 on error.
  454.  * -1: Corrupted packet.
  455.  */
  456. {
  457. #ifdef RSAREF
  458.     R_RSA_PRIVATE_KEY PrivKey;
  459. #endif
  460.     unsigned int blocksize;
  461.     unit temp[MAX_UNIT_PRECISION];
  462.     unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION];
  463.     byte *front, *back;
  464.     int i;
  465.  
  466.     mp_move(temp,P);
  467.     mp_dec(temp);
  468.     mp_mod(DP,D,temp);
  469.     mp_move(temp,Q);
  470.     mp_dec(temp);
  471.     mp_mod(DQ,D,temp);
  472.  
  473. #ifdef RSAREF
  474.     make_RSA_PRIVATE_KEY(&PrivKey, E, D, P, Q, DP, DQ, U, N);
  475.     blocksize = countbytes(inbuf);
  476.     reg2rsaref((byte *)temp, blocksize, inbuf);
  477.     i = RSAPrivateBlock((byte *)temp, &blocksize,
  478.                         (byte *)temp, blocksize, &PrivKey);
  479.     if (i < 0)
  480.         goto ErrorReturn;
  481.     front = (byte *)temp;            /* Start of block */
  482.     back = front + blocksize;        /* End of block */
  483.     i = blocksize - countbytes(N) + 1;    /* Expected # of leading 0's */
  484. #else
  485.     i = mp_modexp_crt(temp, inbuf, P, Q, DP, DQ, U);
  486.     if (i < 0)
  487.         goto ErrorReturn;
  488.     mp_convert_order((byte *)temp);
  489.     front = (byte *)temp;            /* Start of block */
  490.     i = units2bytes(global_precision);
  491.     back = (byte *)front + i;        /* End of block */
  492.     blocksize = countbytes(N) - 1;
  493.     i -= blocksize;                /* Expected # of leading 0's */
  494. #endif
  495.     if (i < 0)                /* This shouldn't happen */
  496.         goto ErrorReturn;
  497.     while (i--)                /* Extra bytes should be 0 */
  498.         if (*front++)
  499.             goto ErrorReturn;
  500.  
  501.     /* How to distinguish old PGP from PKCS formats.
  502.      * PGP packets have a trailing type byte (CK_ENCRYPTED_BYTE),
  503.      * while PKCS formats have it leading.
  504.      */
  505.     if (front[0] != CK_ENCRYPTED_BYTE && back[-1] == CK_ENCRYPTED_BYTE) {
  506.         /* PGP 2.0 format  - padding at the end */
  507.         if (back[-1] != CK_ENCRYPTED_BYTE)
  508.             goto ErrorReturn;
  509.         while (*--back)    /* Skip non-zero random padding */
  510.             ;
  511.     } else {
  512.         /* PKCS format - padding at the beginning */
  513.         if (*front++ != CK_ENCRYPTED_BYTE)
  514.             goto ErrorReturn;
  515.         while (*front++)    /* Skip non-zero random padding */
  516.             ;
  517.     }
  518.     if (back < front)
  519.         goto ErrorReturn;
  520.     memcpy(outbuf, front, back-front);
  521.     mp_burn(temp);
  522.     mp_burn(DP);
  523.     mp_burn(DQ);
  524.     return back-front;
  525.  
  526. ErrorReturn:
  527.     mp_burn(temp);
  528.     mp_burn(DP);
  529.     mp_burn(DQ);
  530.     return -1;
  531. } /* rsa_private_decrypt */
  532.